home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / VirtualDub / system / tracelog.cpp < prev   
C/C++ Source or Header  |  2003-10-01  |  6KB  |  206 lines

  1. #if 0
  2.  
  3. #include <windows.h>
  4.  
  5. #include <vd2/system/vdtypes.h>
  6. #include <vd2/system/List.h>
  7.  
  8. ///////////////////////////////////////////////////////////////////////////
  9. //
  10. // Trace log support.
  11. //
  12. // This only works under Windows NT. :(
  13. //
  14. // It is vital that we generate no constructors here!
  15.  
  16. // !!caution!!    We can deadlock if certain Win32 functions are called while
  17. //                holding this critsec, since the TLS function locks the
  18. //                process critical section.  That means you grab the csect,
  19. //                do something entirely in local code, and get the f*ck out
  20. //                of it as fast as possible.
  21.  
  22. static CRITICAL_SECTION g_csTraceLog;
  23.  
  24. __declspec(thread) volatile VDThreadTraceLog g_tracelog;
  25.  
  26. static __declspec(thread) int g_tracelogidx;
  27.  
  28. #define MAX_TRACE_THREADS        (64)
  29.  
  30. static struct {
  31.     DWORD dwThreadId;
  32.     HANDLE hThreadId;
  33.     VDThreadTraceLog *pTraceLog;
  34. } g_tracetable[MAX_TRACE_THREADS];
  35.  
  36.  
  37. static void NTAPI ThreadLogTLSHook(void *hModule, unsigned long reason, void *reserved) {
  38.     int i;
  39.  
  40.     switch(reason) {
  41.     case DLL_PROCESS_ATTACH:
  42.         InitializeCriticalSection(&g_csTraceLog);
  43.         /* fall through */
  44.     case DLL_THREAD_ATTACH:
  45.         EnterCriticalSection(&g_csTraceLog);
  46.  
  47.         for(i=0; i<MAX_TRACE_THREADS; ++i)
  48.             if (!g_tracetable[i].dwThreadId)
  49.                 break;
  50.  
  51.         g_tracelogidx = -1;
  52.  
  53.         if (i<MAX_TRACE_THREADS) {
  54.  
  55.             if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &g_tracetable[i].hThreadId, NULL, FALSE, DUPLICATE_SAME_ACCESS)) {
  56.                 g_tracelogidx = i;
  57.                 g_tracetable[i].dwThreadId = GetCurrentThreadId();
  58.                 g_tracetable[i].pTraceLog = const_cast<VDThreadTraceLog *>(&g_tracelog);
  59.             }
  60.         }
  61.  
  62.         LeaveCriticalSection(&g_csTraceLog);
  63.  
  64.         break;
  65.     case DLL_THREAD_DETACH:
  66.  
  67.         EnterCriticalSection(&g_csTraceLog);
  68.         if (g_tracelogidx >= 0)
  69.             g_tracetable[g_tracelogidx].dwThreadId = 0;
  70.         CloseHandle(g_tracetable[g_tracelogidx].hThreadId);
  71.         LeaveCriticalSection(&g_csTraceLog);
  72.         break;
  73.     }
  74. }
  75.  
  76. static void VDSuspendResumeAllOtherLoggedThreads(bool bSuspend) {
  77.     DWORD dwMyThreadId = GetCurrentThreadId();
  78.  
  79.     EnterCriticalSection(&g_csTraceLog);
  80.     for(int i=0; i<MAX_TRACE_THREADS; ++i)
  81.         if (g_tracetable[i].dwThreadId && g_tracetable[i].dwThreadId != dwMyThreadId) {
  82.             if (bSuspend)
  83.                 SuspendThread(g_tracetable[i].hThreadId);
  84.             else
  85.                 ResumeThread(g_tracetable[i].hThreadId);
  86.         }
  87.     LeaveCriticalSection(&g_csTraceLog);
  88. }
  89.  
  90. static BOOL CALLBACK VDThreadTraceDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  91.     char buf[1024];
  92.  
  93.     switch(msg) {
  94.     case WM_INITDIALOG:
  95.         {
  96.             DWORD dwMyThreadId = GetCurrentThreadId();
  97.             HWND hwndItem = GetDlgItem(hdlg, 500);
  98.             int i;
  99.  
  100.             for(i=0; i<MAX_TRACE_THREADS; ++i)
  101.                 if (g_tracetable[i].dwThreadId && g_tracetable[i].dwThreadId != dwMyThreadId) {
  102.                     wsprintf(buf, "Thread %08lx - %s", g_tracetable[i].dwThreadId, g_tracetable[i].pTraceLog->desc ? g_tracetable[i].pTraceLog->desc : "(unknown thread)");
  103.  
  104.                     SendMessage(hwndItem, CB_SETITEMDATA, SendMessage(hwndItem, CB_ADDSTRING, 0, (LPARAM)buf), i);
  105.                 }
  106.         }
  107.         return TRUE;
  108.     case WM_COMMAND:
  109.         switch(LOWORD(wParam)) {
  110.         case IDCANCEL:
  111.             EndDialog(hdlg, 0);
  112.             return TRUE;
  113.         case 500:
  114.             if (HIWORD(wParam) == CBN_SELCHANGE) {
  115.                 HWND hwndItem = GetDlgItem(hdlg, 501);
  116.                 VDThreadTraceLog *pLog = g_tracetable[SendMessage((HWND)lParam, CB_GETITEMDATA, SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0), 0)].pTraceLog;
  117.  
  118.                 SendMessage(hwndItem, LB_RESETCONTENT, 0, 0);
  119.  
  120.                 for(int i=1; i<=VDTRACELOG_SIZE; ++i) {
  121.                     const char *psz = pLog->log[(pLog->idx + i) & (VDTRACELOG_SIZE-1)].s;
  122.                     const long v = pLog->log[(pLog->idx + i) & (VDTRACELOG_SIZE-1)].v;
  123.  
  124.                     if (psz) {
  125.                         wsprintf(buf, psz, v);
  126.                         SendMessage(hwndItem, LB_ADDSTRING, 0, (LPARAM)buf);
  127.                     }
  128.                 }
  129.             }
  130.             return TRUE;
  131.         }
  132.         return TRUE;
  133.     }
  134.     return FALSE;
  135. }
  136.  
  137. static DWORD WINAPI VDThreadTraceStart(LPVOID lpTemplate) {
  138.     VDSuspendResumeAllOtherLoggedThreads(true);
  139.     DialogBox(GetModuleHandle(NULL), (LPCTSTR)lpTemplate, NULL, VDThreadTraceDlgProc);
  140.     VDSuspendResumeAllOtherLoggedThreads(false);
  141.  
  142.     return 0;
  143. }
  144.  
  145. void VDThreadTrace(LPCTSTR lpTemplate) {
  146.     DWORD dwThreadId;
  147.  
  148.     HANDLE hThread = CreateThread(NULL, 0, VDThreadTraceStart, (void *)lpTemplate, 0, &dwThreadId);
  149.  
  150.     if (hThread)
  151.         CloseHandle(hThread);
  152. }
  153.  
  154. ///////////////////////////////////////////////////////////////////////////
  155. //
  156. // To hook all the thread logs together, we need to be able to intercept thread
  157. // creation and destruction.  The easiest way to do this is to hook into the TLS
  158. // callbacks.  VC++ doesn't allow us to use thread local constructors, so we should
  159. // be able to hook into the TLS constructor list, marked by the .CRT$XLA and .CRT$XLZ
  160. // segments.  Unfortunately, the .CRT$XLA segment starts with a null longword which
  161. // immediately terminates the list.
  162. //
  163. // Thus, as usual, we do it ourself.  This section replaces tlssup.obj in the
  164. // run-time library.
  165.  
  166. extern "C" extern unsigned long _tls_index=0;
  167.  
  168. static PIMAGE_TLS_CALLBACK tls_functions[]={
  169.     ThreadLogTLSHook,
  170.     NULL
  171. };
  172.  
  173. // I think these were meant for thread local hooks, but they don't work properly
  174. // because of the stupid zero. :(
  175.  
  176. #pragma data_seg(".CRT$XLA")
  177. void (__cdecl *__xl_a)()=0;
  178. #pragma data_seg(".CRT$XLZ")
  179. void (__cdecl *__xl_z)()=0;
  180.  
  181. // Presumably, the TLS area that is copied between all functions.  These need
  182. // to be non-const, because const data doesn't need to be TL, does it?
  183.  
  184. #pragma data_seg(".tls")
  185. extern "C" int _tls_start=0;
  186. #pragma data_seg(".tls$ZZZ")
  187. extern "C" int _tls_end=0;
  188.  
  189. extern "C" const struct _IMAGE_TLS_DIRECTORY32 _tls_used = {
  190.     (DWORD)&_tls_start,
  191.     (DWORD)&_tls_end,
  192. #ifndef INVALID_SET_FILE_POINTER        // VC6 includes
  193.     (LPDWORD)&_tls_index,
  194.     (void(__stdcall**)(void*,DWORD,void *))tls_functions,
  195. #else        // PlatSDK includes
  196.     (DWORD)&_tls_index,
  197.     (DWORD)tls_functions,
  198. #endif
  199.     0,
  200.     0
  201. };
  202.  
  203. #pragma data_seg()
  204.  
  205. #endif
  206.